package two.phase.termination;

/**
 * Created by Administrator on 2017/3/16.
 */

/**
 * 可停止的抽象线程
 */
public abstract class AbstractTerminationThread  extends Thread implements Terminatable{

    public final TerminationToken terminationToken;

    public AbstractTerminationThread() {
        this(new TerminationToken());
    }

    public AbstractTerminationThread(TerminationToken terminationToken) {
        super();
        this.terminationToken = terminationToken;
        terminationToken.register(this);
    }


    protected abstract void doRun() throws Exception;

    protected void doCleanup(Exception cause){
        // do nothing
    }

    protected void doTerminiate(){
        //do nothing.
    }

    @Override
    public void run() {
        Exception ex = null;

        try{
            for(;;){
                if(terminationToken.isToShutdown() && terminationToken.reservations.get() <= 0){
                        break;
                }
                doRun();
            }
        }catch (Exception e){
            ex=e;
        }finally {
            try {
                doCleanup(ex);
            }finally {
                terminationToken.notifyThreadTermination(this);
            }
        }
    }

    @Override
    public void interrupt() {
        terminate();
    }

    @Override
    public void terminate() {
        terminationToken.setToShutdown(true);
        try {
            doTerminiate();
        }finally {
            if(terminationToken.reservations.get() <= 0 ){
                super.interrupt();
            }
        }
    }

    public void terminate(boolean waitUtilThreadTerminated) {
        terminate();
        if(waitUtilThreadTerminated) {
            try {
                this.join();
            }catch (InterruptedException e){
                Thread.currentThread().interrupt();
            }
        }
    }
}
